<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>深入面向对象</title>
</head>
<body>
<!--
    面向过程
    面向过程: 分析出解决问题所需要的步骤，任期内后用函数把这些步骤一步一步实现，使用的时候再一个一个的调用
    优点:
        性能比面向对象高，适合跟硬件联系很紧密的东西，比如单片机编程
    缺点:
        没有面向对象更易维护、易复用、易拓展
-->
<!--
    面向对象
    面向对象: 把事物分解成一个一个的对象，然后对象之间分工与合作
    面向对象三大特征：
        封装、继承、多态
    优缺点和面向过程相反

-->
</body>
<script>
    // 封装特性 ---- 构造函数 ---- 把公共的属性和方法封装到 Star 构造函数里面
    /*
       缺点: 属性和方法在创建时均会开启一个新的堆空间,并向栈返回一个地址,
            属性开新空间保存无所谓但是方法也开新空间保存了, 不同的对象方法可能是一样的,这样会导致内存浪费的问题
    */
    function Star(name, age) {
        this.name = name
        this.age = age
        this.sing = function () {
            console.log('唱歌')
        }
    }
    const ldh = new Star('刘德华' , 55)
    const zxy = new Star('张学友' , 58)
    console.log(ldh)

    // 继承特性 ---- 原型 ---- 解决构造函数多次开辟相同内容的空间导致内存浪费的问题
    /*
    * 构造函数通过原型分配的函数是所有对象所共享的
    * JS规定: 每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也成为原型对象
    *        这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
    * 使用: 可以把那些不变的方法直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
    * 注意: 构造函数和原型对象中的this都指向 实例化 的对象
    * 语法: Star.prototype.函数名 = function() {}
    * 原型中的this: prototype中的函数原型指向的对象还是new的调用者
    * 原型中的constructor属性:
    *
    * */
    Star.prototype.dance = function () {
        console.log('跳舞')
    }
    // 假设生成了n个对象 , 那么 sing 被开辟了n个空间 , 而dance只被开辟了1个空间
    ldh.dance()
    zxy.dance()
    // 


</script>
</html>